package pl.iachoo.ctl.tabory.ui.base.editor;

import javax.print.attribute.standard.Severity;

import org.apache.log4j.Logger;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.ui.forms.widgets.Form;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.wb.swt.ResourceManager;

import pl.iachoo.ctl.tabory.ui.properties.Messages;
import pl.iachoo.ctl.tabory.ui.selection.ISelection;

public abstract class AbstractEditorPart<S extends ISelection> extends ViewPart {

	private final Logger logger = Logger.getLogger(AbstractEditorPart.class);

	protected S selection;

	protected final FormToolkit formToolkit;
	protected Form form;
	protected ToolItem toolItemSave;
	protected ToolItem toolItemCancel;

	private boolean isDirty;

	protected Action editorSaveAction;
	protected Action editorCancelAction;

	public AbstractEditorPart() throws Exception {
		BusyIndicator.showWhile(Display.getDefault(), new Runnable() {
			@Override
			public void run() {
				try {
					selection = initSelection();
				} catch (Exception e) {
					logger.error(e.getMessage(), e);
					openErrorDialog(e);
				}
			}
		});
		createActions();
		formToolkit = new FormToolkit(Display.getDefault());
		setDirty(false);
	}

	private void createActions() {
		editorSaveAction = new Action(Messages.getString("common.save")) {
			@Override
			public void run() {
				if (!isDirty) {
					logger.debug("Could not save not dirty editor. Dirty flag value is: "
							+ isDirty + ". Something is relly bad");
					return;
				}
				logger.debug("Run menu action: save editor.");
				BusyIndicator.showWhile(form.getDisplay(), new Runnable() {
					@Override
					public void run() {
						try {
							doSave();
						} catch (Exception e) {
							logger.error(e.getMessage(), e);
							openErrorDialog(e);
						}
					}
				});
			}
		};
		editorCancelAction = new Action(Messages.getString("common.cancel")) {
			@Override
			public void run() {
				if (!isDirty) {
					logger.debug("Could not cancel not dirty editor. Dirty flag value is: "
							+ isDirty + ". Something is relly bad");
					return;
				}
				logger.debug("Run menu action: cancel editor.");
				BusyIndicator.showWhile(form.getDisplay(), new Runnable() {
					@Override
					public void run() {
						try {
							doCancel();
						} catch (Exception e) {
							logger.error(e.getMessage(), e);
							openErrorDialog(e);
						}
					}
				});
			}
		};
		editorSaveAction.setImageDescriptor(ResourceManager
				.getPluginImageDescriptor("org.eclipse.ui",
						"/icons/full/etool16/save_edit.gif"));
		editorCancelAction.setImageDescriptor(ResourceManager
				.getPluginImageDescriptor("org.eclipse.ui",
						"/icons/full/etool16/clear.gif"));
	}

	@Override
	public void createPartControl(Composite parent) {
		logger.debug("Creating part control");
		form = formToolkit.createForm(parent);
		formToolkit.paintBordersFor(form);
		form.getToolBarManager().add(editorSaveAction);
		form.getToolBarManager().add(editorCancelAction);
		form.getToolBarManager().update(true);
		logger.debug("Initializing GUI.");
		initGui(parent);
		logger.debug("Post-initializing GUI.");
		postInitGui(parent);
	}

	protected abstract void initGui(Composite parent);

	protected abstract void postInitGui(Composite parent);

	protected abstract void doSave() throws Exception;

	protected abstract void doCancel() throws Exception;

	protected abstract S initSelection() throws Exception;

	public boolean isDirty() {
		return isDirty;
	}

	public void setDirty(boolean isDirty) {
		logger.debug("Set editor state dirty to: " + isDirty);
		// TODO change editor name if editro is dirty
		this.isDirty = isDirty;
		editorSaveAction.setEnabled(isDirty);
		editorCancelAction.setEnabled(isDirty);
	}

	public void openErrorDialog(Exception e) {
		if (e == null) {
			return;
		}
		String cause;
		if (e.getCause() != null) {
			cause = e.getCause().toString();
		} else {
			cause = e.getMessage();
		}
		Status status = new Status(Severity.ERROR.getValue(),
				"pl.iachoo.ctl.tabory.ui", cause);
		ErrorDialog.openError(getSite().getShell(),
				Messages.getString("common.dialog.title.error"), e.toString(),
				status);
	}

	public String getExceptionStacTrace() {
		return null;
	}

}
